package router

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"signature-service/controllers"
	"signature-service/global"
	"strconv"
	"time"
)

// CustomResponseWriter 自定义响应记录器
type CustomResponseWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (w CustomResponseWriter) Write(b []byte) (int, error) {
	w.body.Write(b)                  // 将响应数据写入缓冲区
	return w.ResponseWriter.Write(b) // 写入实际响应
}

// LoggerMiddleware 自定义日志中间件
func LoggerMiddleware(logger *zap.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		// 替换默认的 ResponseWriter
		customWriter := &CustomResponseWriter{
			ResponseWriter: c.Writer,
			body:           bytes.NewBufferString(""),
		}
		c.Writer = customWriter
		// 处理请求
		c.Next()

		// 获取请求参数
		var params string
		if c.Request.Method == "GET" {
			params = c.Request.URL.Query().Encode()
		} else {
			// 对于 POST 或其他方法，可以读取请求体
			// 注意：需要确保读取请求体不会影响后续处理
			body, err := c.GetRawData()
			if err == nil {
				params = string(body)
			}
			c.Request.Body = http.NoBody // 重置请求体以便后续处理
		}

		// 记录请求日志
		logger.Info("请求日志",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.String("params", params),
			zap.Int("status", c.Writer.Status()),
			zap.Duration("latency", time.Since(start)),
			zap.String("client_ip", c.ClientIP()),
			zap.Time("request_time", start),                    // 记录请求时间
			zap.String("response", customWriter.body.String()), // 记录响应数据
		)
	}
}

// VerifySign 校验签名
func VerifySign(logger *zap.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取请求参数
		id := c.DefaultQuery("id", "")
		to := c.DefaultQuery("to", "")
		tokenAddress := c.DefaultQuery("tokenAddress", "")
		value := c.DefaultQuery("value", "")
		rpcUrl := c.DefaultQuery("rpcUrl", "")
		nonce := c.DefaultQuery("nonce", "")
		timestamp := c.DefaultQuery("timestamp", "")
		encryptData := c.DefaultQuery("encryptData", "")

		// 校验时间戳
		timestampInt, err := strconv.Atoi(timestamp)
		if err != nil || time.Now().Unix()-int64(timestampInt) > 60 { // 时间戳有效期为1分钟
			logger.Info("时间戳校验失败", zap.String("timestamp", timestamp))
			c.JSON(200, global.Fail("时间戳校验失败"))
			c.Abort()
			return
		}

		//MD5加密
		data := []byte(id + to + rpcUrl + value + tokenAddress + nonce + timestamp + "Zhe9eyanwUd1")
		hash := md5.Sum(data)
		md5String := hex.EncodeToString(hash[:])
		if encryptData != md5String {
			logger.Info("非法请求", zap.String("encryptData", encryptData), zap.String("md5String", md5String))
			c.JSON(200, global.Fail("非法请求"))
			c.Abort()
			return
		}

		// 处理请求
		c.Set("id", id)
		c.Set("to", to)
		c.Set("tokenAddress", tokenAddress)
		c.Set("value", value)
		c.Set("rpcUrl", rpcUrl)
		c.Next()
	}
}

func RegisterRoute(logger *zap.Logger) *gin.Engine {
	router := gin.New()
	// 使用自定义日志中间件
	router.Use(LoggerMiddleware(logger))
	api := router.Group("/api")
	var GetSignController = controllers.NewSignController()
	api.GET("/generateAddress", GetSignController.GenerateAddress)
	api.GET("/getSign", VerifySign(logger), GetSignController.GetSign)
	api.GET("/getTokenForTokenSign", GetSignController.GetTokenForTokenSign)
	// 更换加密方式
	api.GET("/updateDecode", GetSignController.UpdateDecode)

	return router
}
